package functional_thinking._1;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Words {
	
	private static String text = 
			"Failure no longer will be my payment for struggle. Just as nature made no provision for my body to tolerate pain neither has it made any provision for my life to suffer failure. Failure, like pain, is alien to my life. In the past I accepted it as I accepted pain. Now I reject it and I am prepared for wisdom and principles which will guide me out of the shadows into the sunlight of wealth, position, and happiness far beyond my most extravagant dreams until even the golden apples in the Garden of Hesperides will seem no more than my just reward. Time teaches all things to him who lives forever but I have not the luxury of eternity. Yet within my allotted time I must practice the art of patience for nature acts never in haste. To create the olive, king of all trees, a hundred years is required. An onion plant is old in nine weeks. I have lived as an onion plant. It has not pleased me. Now I wouldst become the greatest of olive trees and, in truth, the greatest of salesman.";

	private static Set<String> NON_WORDS = new HashSet<>() {
		{
			add("the");
			add("and");
			add("of");
			add("to");
			add("a");
			add("i");
			add("it");
			add("in");
			add("or");
			add("is");
			add("d");
			add("s");
			add("as");
			add("so");
			add("but");
			add("be");
		}
	};

	public static Map wordFreq(String words) {
		TreeMap<String, Integer> wordMap = new TreeMap<>();
		Matcher m = Pattern.compile("\\w+").matcher(words);
		while (m.find()) {
			String word = m.group().toLowerCase();
			if (!NON_WORDS.contains(word)) {
				wordMap.put(word, wordMap.getOrDefault(word, 0) + 1);
			}
		}
		return wordMap;
	}
	
	public static Map wordFreq2(String words) {
		TreeMap<String, Integer> wordMap = new TreeMap<>();
		regexToList(words, "\\w+").stream()
					.map(w -> w.toLowerCase())
					.filter(w -> !NON_WORDS.contains(w))
					.forEach(w -> wordMap.put(w, wordMap.getOrDefault(w, 0) + 1));
		return wordMap;
	}
	
	private static List<String> regexToList(String words, String regex) {
		List<String> wordList = new ArrayList<>();
		Matcher m = Pattern.compile(regex).matcher(words);
		while(m.find()) {
			wordList.add(m.group());
		}
		return wordList;
	}
	
	public static void main(String[] args) {
		System.out.println(wordFreq(text));
		System.out.println(wordFreq2(text));
	}

}
